home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / DYN401.ZIP / dpp / ostream.d < prev    next >
Text File  |  1996-12-08  |  13KB  |  632 lines

  1.  
  2. /*
  3.  *
  4.  *    Copyright (c) 1994-1996 Algorithms Corporation
  5.  *    3020 Liberty Hills Drive
  6.  *    Franklin, TN  37067
  7.  *
  8.  *    ALL RIGHTS RESERVED.
  9.  *
  10.  *
  11.  *
  12.  */
  13.  
  14.  
  15.  
  16. #include <ctype.h>
  17. #include <stdarg.h>
  18. #include <string.h>
  19.  
  20. #include "dpp.h"
  21.  
  22.  
  23. #define CONVERT_SUPER
  24.  
  25.  
  26. #define strne(a, b)    strcmp(a, b)
  27. #define streq(a, b)    !strcmp(a, b)
  28.  
  29. #define istart(x)    (isalpha(x)  ||  (x) == '_')
  30. #define irest(x)    (isalnum(x)  ||  (x) == '_')
  31.  
  32.  
  33. #ifdef    unix
  34. #define RMODE    "r"
  35. #define WMODE    "w"
  36. #else
  37. #define RMODE    "rt"
  38. #define WMODE    "wt"
  39. #endif
  40.  
  41.  
  42.  
  43. defclass OutputStream  {
  44.     iStream;        /*  output stream or NULL if none  */
  45.     iSFile;            /*  source file name    */
  46.     iTFile;            /*  target file name    */
  47.     long    iILine;        /*  input line number    */
  48.     long    iOLine;        /*  current output line    (as seen by the compiler) */
  49.     long    iRLine;        /*  real output line number  */
  50.     int    iBraceLevel;
  51.     int    iParenLevel;
  52.     int    iBlbl;        /*  beginning of line brace level  */
  53.     char    iPllc;        /*  previous line last char       */
  54.     iOutputList;
  55.     iCVars;            /*  class variables (a Set)    */
  56.     iIVars;            /*  instance variables (a Set)    */
  57.     iCName;            /*  class name            */
  58. };
  59.  
  60.  
  61.  
  62. extern    objrtn open_file(char *file,char *mode);
  63.  
  64. extern    int    ErrorCode, LineDirectives;
  65.  
  66.  
  67. cmeth    gNew()
  68. {
  69.     return gShouldNotImplement(self, "gNew");
  70. }
  71.  
  72. cmeth    gNewWithStrStr(char *file, char *ifile)
  73. {
  74.     object    obj = gNew(super);
  75.     ivType    *iv = ivPtr(obj);
  76.     iSFile = gNewWithStr(String, ifile);
  77.     iTFile = gNewWithStr(String, file);
  78. #ifndef    unix
  79.     gToLower(iSFile);
  80.     gToLower(iTFile);
  81. #endif
  82.     iStream = file ? open_file(file, WMODE) : (object) NULL;
  83.     iOutputList = gNew(LinkList);
  84.     iRLine = iOLine = 1L;
  85.     iPllc = ';';
  86.     return obj;
  87. }
  88.  
  89. static    int    sub(object tkn, object sym, object vars, char *exp)
  90. {
  91.     long    line;
  92.     if (!vars  ||  !gFind(vars, sym))
  93.         return 0;
  94.     line = gLineNumber(tkn);
  95.     gAddBefore(tkn, gNewToken(Token, exp, line, 0));
  96.     gAddBefore(tkn, gNewToken(Token, "->", line, 0));
  97.     return 1;
  98. }
  99.  
  100. static    int    do_var_sub(ivType *iv)
  101. {
  102.     object    tkn, sym;
  103.     char    *p, *pstr = NULL;
  104.     int    res = 0;
  105.     char    cvar[80];
  106.  
  107.     sprintf(cvar, "%s_cv", gStringValue(iCName));
  108.     for (tkn = gFirst(iOutputList) ; tkn ; tkn = gNext(tkn), pstr=p)  {
  109.         p = gStringValue(tkn);
  110.         if (!istart(*p))
  111.             continue;
  112.         if (!pstr  ||  strne(pstr, "->")  &&  strne(pstr, "."))  {
  113.             sym = gToken(tkn);
  114.             if (sub(tkn, sym, iIVars, "iv"))
  115.                 res = 1;
  116.             else
  117.                 sub(tkn, sym, iCVars, cvar);
  118.         }
  119.     }
  120.     return res;
  121. }
  122.  
  123. #ifdef    CONVERT_SUPER
  124.  
  125. /*  convert  gen(super obj, args)   ->
  126.     (_super_save_=(obj), oSuper(cls, gen, _super_save_)(_super_save_, args)) */
  127.  
  128.  
  129. static    objrtn    make_arg(object frst, object lst, int *simple)
  130. {
  131.     object    arg;
  132.     int    pos;
  133.     char    *p1=NULL, *p2=NULL, *p3=NULL;
  134.  
  135.     arg = gNew(LinkList);
  136.     for (pos=0 ; frst != lst ; frst=gNext(frst))  {
  137.         switch (++pos)  {
  138.         case 1:        p1 = gStringValue(frst);    break;
  139.         case 2:        p2 = gStringValue(frst);    break;
  140.         case 3:        p3 = gStringValue(frst);    break;
  141.         }
  142.         gAddLast(arg, gCopy(frst));
  143.     }
  144.     *simple = pos == 1  &&  istart(*p1)  ||
  145.           pos == 3  &&  streq(p1, "(")  &&  istart(*p2)  &&
  146.               streq(p3, ")");
  147.     return arg;
  148. }
  149.  
  150.  
  151. #define OUTT(t)    if (tkn)                \
  152.             gAddBefore(tkn, t);        \
  153.         else                    \
  154.             gAddLast(iOutputList, t)
  155.  
  156.  
  157.  
  158. static    int    convert_super(ivType *iv)
  159. {
  160.     object    tkn;
  161.     char    *p, *pstr = NULL, *ppstr = NULL, *tp;
  162.     int    paren;
  163.     object    frst;    /*  first token after super    */
  164.     object    lst;    /*  token at end of super arg   */
  165.     object    gen;    /*  generic token        */
  166.     object    arg;    /*  list of tokens after super     */
  167.     object    t;    /*  temp token pointer        */
  168.     long    line;    /*  input line of token     */
  169.     int    simple;    /*  simple case of super arg    */
  170.     char    cname[80];
  171.  
  172.     for (tkn = gFirst(iOutputList) ; tkn ; tkn=gNext(tkn), ppstr=pstr, pstr=p)  {
  173.         p = gStringValue(tkn);
  174.         if (strne(p, "super"))
  175.             continue;
  176.         if (!pstr  ||  strne(pstr, "("))
  177.             continue;
  178.         if (!ppstr  ||  !istart(*ppstr))
  179.             continue;
  180.  
  181.         frst = gNext(tkn);
  182.         if (!frst)
  183.             continue;
  184.  
  185.         line = gLineNumber(tkn);
  186.  
  187.         /*  check and handle implied self  */
  188.         tp = gStringValue(frst);
  189.         if (streq(tp, ",")  ||  streq(tp, ")"))  {
  190.             t = gNewToken(Token, "self", line, 0);
  191.             gAddBefore(frst, t);
  192.             frst = t;
  193.         }
  194.  
  195.         paren = streq(gStringValue(frst), "(");
  196.  
  197.         /*  get end of obj  */
  198.  
  199.         for (lst=frst ; 1 ; )  {
  200.             lst = gNext(lst);
  201.             if (!lst)
  202.                 break;
  203.             tp = gStringValue(lst);
  204.             if (streq(tp, ")"))
  205.                 paren--;
  206.             else if (streq(tp, "("))
  207.                 paren++;
  208.             if (streq(tp, ",")  &&  !paren  ||  paren < 0)
  209.                 break;
  210.         }
  211.  
  212.         /*  make tkn point to the generic  */
  213.  
  214.         tkn = gPrevious(tkn);
  215.         tkn = gPrevious(tkn);
  216.  
  217.         /*  get copy of generic name  */
  218.  
  219.         gen = gCopy(tkn);
  220.  
  221.         /*  make list of tokens after super  */
  222.  
  223.         arg = make_arg(frst, lst, &simple);
  224.  
  225.         /*  delete  gen(super arg from iOutputList  */
  226.  
  227.         for ( ; tkn != lst ; tkn = t) {
  228.             t = gNext(tkn);
  229.             gDispose(tkn);
  230.         }
  231.  
  232.         /*  make tkn point to whatever follows gen(super obj  */
  233.  
  234.         tkn = lst;
  235.  
  236.         /*  create desired code  */
  237.  
  238.         if (simple)  {
  239.             t = gNewToken(Token, "oSuper", line, 0);
  240.             OUTT(t);
  241.  
  242.             t = gNewToken(Token, "(", line, 0);
  243.             OUTT(t);
  244.  
  245.             sprintf(cname, "%s_c", gStringValue(iCName));
  246.             t = gNewToken(Token, cname, line, 0);
  247.             OUTT(t);
  248.  
  249.             t = gNewToken(Token, ",", line, 1);
  250.             OUTT(t);
  251.  
  252.             OUTT(gen);
  253.  
  254.             t = gNewToken(Token, ",", line, 1);
  255.             OUTT(t);
  256.  
  257.             for (t=gFirst(arg) ; t ; t=gNext(t))
  258.                 OUTT(gCopy(t));
  259.  
  260.             t = gNewToken(Token, ")", line, 0);
  261.             OUTT(t);
  262.  
  263.             t = gNewToken(Token, "(", line, 0);
  264.             OUTT(t);
  265.             
  266.             while (t = gFirst(arg))  {
  267.                 gRemove(t);
  268.                 OUTT(t);
  269.             }
  270.  
  271.             DISPOSE(arg);
  272.  
  273.         } else {
  274.             t = gNewToken(Token, "(", line, 0);
  275.             OUTT(t);
  276.  
  277.             t = gNewToken(Token, "_super_save_", line, 0);
  278.             OUTT(t);
  279.  
  280.             t = gNewToken(Token, "=", line, 0);
  281.             OUTT(t);
  282.  
  283.             t = gNewToken(Token, "(", line, 0);
  284.             OUTT(t);
  285.  
  286.             while (t = gFirst(arg))  {
  287.                 gRemove(t);
  288.                 OUTT(t);
  289.             }
  290.             DISPOSE(arg);
  291.  
  292.             t = gNewToken(Token, ")", line, 0);
  293.             OUTT(t);
  294.  
  295.             t = gNewToken(Token, ",", line, 1);
  296.             OUTT(t);
  297.  
  298.             t = gNewToken(Token, "oSuper", line, 0);
  299.             OUTT(t);
  300.  
  301.             t = gNewToken(Token, "(", line, 0);
  302.             OUTT(t);
  303.  
  304.             sprintf(cname, "%s_c", gStringValue(iCName));
  305.             t = gNewToken(Token, cname, line, 0);
  306.             OUTT(t);
  307.  
  308.             t = gNewToken(Token, ",", line, 1);
  309.             OUTT(t);
  310.  
  311.             OUTT(gen);
  312.  
  313.             t = gNewToken(Token, ",", line, 0);
  314.             OUTT(t);
  315.  
  316.             t = gNewToken(Token, "_super_save_", line, 0);
  317.             OUTT(t);
  318.  
  319.             t = gNewToken(Token, ")", line, 0);
  320.             OUTT(t);
  321.  
  322.             t = gNewToken(Token, "(", line, 0);
  323.             OUTT(t);
  324.  
  325.             t = gNewToken(Token, "_super_save_", line, 0);
  326.             OUTT(t);
  327.  
  328.             /*  find the ) at the end of the whole thing  */
  329.  
  330.             paren = 1;
  331.             while (paren  &&  tkn)  {
  332.                 p = gStringValue(tkn);
  333.                 if (streq(p, "("))
  334.                     paren++;
  335.                 else if (streq(p, ")"))
  336.                     paren--;
  337.                 if (paren)
  338.                     tkn = gNext(tkn);
  339.             }
  340.             if (!tkn)  {
  341.                 ErrorCode = 1;
  342.                 vPrintf(stdoutStream, "Error on line %ld\n", line);
  343.                 vPrintf(stdoutStream, "Expression containing super - bad syntax\n");
  344.             }
  345.  
  346.             t = gNewToken(Token, ")", tkn ? gLineNumber(tkn) : line, 0);
  347.             OUTT(t);
  348.         }            
  349.  
  350.         return 1;   /*  could be more - re-scan  */
  351.     }
  352.     return 0;   /*  none found - no re-scan  */
  353. }
  354.  
  355. #endif
  356.  
  357. /*  flush a single line  */
  358.  
  359. imeth    gFlush()
  360. {
  361.     int    i, pp;
  362.     object    tkn;
  363.     char    *p=NULL, c=0;
  364.  
  365.     if (!iStream)
  366.         return self;
  367.  
  368.     if (iIVars  ||  iCVars)
  369.         do_var_sub(iv);
  370.  
  371. #ifdef    CONVERT_SUPER
  372.     while (convert_super(iv));
  373. #endif
  374.  
  375.     tkn = gFirst(iOutputList);
  376.     if (tkn  &&  iILine  &&  iOLine != iILine)
  377.         if (iILine > iOLine  &&  iILine < iOLine+5)
  378.             while (iOLine != iILine)  {
  379.                 gPuts(iStream, "\n");
  380.                 iOLine++;
  381.                 iRLine++;
  382.             }
  383.         else
  384.             gSLineDirective(self);
  385.     
  386.     pp = tkn  &&  *(p=gStringValue(tkn)) == '#';
  387.     if (tkn  &&  !pp)
  388.         for (i=iBlbl-(*p == '}')+(*p != '{' && iPllc != ';'  &&  iPllc != '{' &&  iPllc != '}' && iPllc != ':') ; i-- > 0 ; )
  389.             gPuts(iStream, "\t");
  390.     for ( ; tkn ; tkn = gFirst(iOutputList))  {
  391.         p = gStringValue(tkn);
  392.         if (irest(*p)  &&  irest(c))
  393.             gPuts(iStream, " ");
  394.         gPuts(iStream, p);
  395.         if (gSpace(tkn))  {
  396.             gPuts(iStream, " ");
  397.             c = 0;
  398.         } else
  399.             c = *p;
  400.         iPllc = *p;
  401.         gDeepDisposeFirst(iOutputList);
  402.     }
  403.     if (pp)
  404.         iPllc = ';';
  405.     gPuts(iStream, "\n");
  406.     iOLine++;
  407.     iRLine++;
  408.     iILine = 0L;
  409.     iBlbl = iBraceLevel;
  410.     return self;
  411. }
  412.  
  413. /*  flush an entire method  */
  414.  
  415. imeth    gFlushm()
  416. {
  417.     int    i;
  418.     object    tkn;
  419.     char    *p, c=0, *cname, ctype[80];
  420.  
  421.     if (!iStream)
  422.         return self;
  423.     
  424. #define    ADD(s, t)    gAddAfter(tkn, gNewToken(Token, t, 0L, s))
  425.     
  426.     if ((iIVars  ||  iCVars)  &&  do_var_sub(iv))  {
  427.         tkn = gFirst(iOutputList);
  428.         sprintf(ctype, "%s_iv_t", cname = gStringValue(iCName));
  429.         ADD(0, ";");
  430.         ADD(0, ")");
  431.         ADD(0, "self");
  432.         ADD(1, ",");
  433.         ADD(0, cname);
  434.         ADD(0, "(");
  435.         ADD(0, "GetIVs");
  436.         ADD(1, "=");
  437.         ADD(1, "iv");
  438.         ADD(0, "*");
  439.         ADD(1, ctype);
  440.     }
  441.  
  442. #ifdef    CONVERT_SUPER
  443.     while (convert_super(iv));
  444. #endif
  445.  
  446.     for (tkn=gFirst(iOutputList) ; tkn ; tkn=gFirst(iOutputList))  {
  447.         iILine = gLineNumber(tkn);
  448.         if (iILine  &&  iOLine != iILine)  {
  449.             if (iILine > iOLine  &&  iILine < iOLine+5)
  450.                 while (iOLine != iILine)  {
  451.                     gPuts(iStream, "\n");
  452.                     iOLine++;
  453.                     iRLine++;
  454.                 }
  455.             else
  456.                 gSLineDirective(self);
  457.             p = gStringValue(tkn);
  458.             iBlbl = iBraceLevel;
  459.             if (*p != '#')
  460.                 for (i=iBlbl-(*p == '}')+(*p != '{' && iPllc != ';'  &&  iPllc != '{' &&  iPllc != '}' && iPllc != ':') ; i-- > 0 ; )
  461.                     gPuts(iStream, "\t");
  462.         } else
  463.             p = gStringValue(tkn);
  464.     
  465.         if (irest(*p)  &&  irest(c))
  466.             gPuts(iStream, " ");
  467.         gPuts(iStream, p);
  468.         iPllc = c = *p;
  469.         if (c == '(')
  470.             iParenLevel++;
  471.         else if (c == ')')  {
  472.             if (iParenLevel)
  473.                 iParenLevel--;
  474.         } else if (c == '{')
  475.             iBraceLevel++;
  476.         else if (c == '}')  {
  477.             if (iBraceLevel)
  478.                 iBraceLevel--;
  479.         }
  480.         if (gSpace(tkn))  {
  481.             gPuts(iStream, " ");
  482.             c = 0;
  483.         }
  484.         gDeepDisposeFirst(iOutputList);
  485.     }
  486.     gPuts(iStream, "\n");
  487.     iOLine++;
  488.     iRLine++;
  489.     iILine = 0L;
  490.     iBlbl = iBraceLevel;
  491.     return self;
  492. }
  493.  
  494. imeth    object    gDispose, gDeepDispose ()
  495. {
  496.     gFlush(self);
  497.     if (iStream)
  498.         gDispose(iStream);
  499.     gDispose(iSFile);
  500.     gDispose(iTFile);
  501.     gDeepDispose(iOutputList);
  502.     return gDispose(super);
  503. }
  504.  
  505. imeth    gPut(tkn)
  506. {
  507.     char    c = *gStringValue(tkn);
  508.     long    ln = gLineNumber(tkn);
  509.  
  510.     if (!iStream)  {
  511.         DISPOSE(tkn);
  512.         return self;
  513.     }
  514.  
  515.     if (!iILine)
  516.         iILine = ln;
  517.     else if (ln  &&  iILine != ln)  {
  518.         gFlush(self);
  519.         iILine = ln;
  520.     }
  521.  
  522.     gAddLast(iOutputList, tkn);
  523.     if (!ln  &&  (!iParenLevel  &&  c == ';'  ||  c == '}'  ||  c == '{'  ||  c == ':'))
  524.         gFlush(self);
  525.     if (c == '(')
  526.         iParenLevel++;
  527.     else if (c == ')')  {
  528.         if (iParenLevel)
  529.             iParenLevel--;
  530.     } else if (c == '{')
  531.         iBraceLevel++;
  532.     else if (c == '}')  {
  533.         if (iBraceLevel)
  534.             iBraceLevel--;
  535.     }
  536.     return self;
  537. }
  538.  
  539. /*  put token at end of list but don't output (collect entire method)  */
  540.  
  541. imeth    gPutm(tkn)
  542. {
  543.     if (iStream)
  544.         gAddLast(iOutputList, tkn);
  545.     else
  546.         DISPOSE(tkn);
  547.     return self;
  548. }
  549.  
  550. static    int    count_nl(char *s)
  551. {
  552.     int    n = 0;
  553.     for ( ; *s ; s++)
  554.         if (*s == '\n')
  555.             n++;
  556.     return n;
  557. }
  558.  
  559. imeth    int    gPuts(char *str)
  560. {
  561.     iOLine = -20L;
  562.     iRLine += count_nl(str);
  563.     iILine = 0L;
  564.     return iStream ? gPuts(iStream, str) : strlen(str);
  565. }
  566.  
  567. ivmeth    int    vPrintf(char *fmt, ...)
  568. {
  569.     char    buf[256];
  570.     MAKE_REST(fmt);
  571.  
  572.     vsprintf(buf, fmt, _rest_);
  573.     iOLine = -20L;
  574.     iRLine += count_nl(buf);
  575.     iILine = 0L;
  576.     return iStream ? gPuts(iStream, buf) : strlen(buf);
  577. }
  578.  
  579. imeth    gSetOSVars(cname, cvs, ivs)
  580. {
  581.     iCName = cname;
  582.     iCVars = gSize(cvs) ? cvs : (object) NULL;
  583.     iIVars = gSize(ivs) ? ivs : (object) NULL;
  584.     return self;
  585. }
  586.  
  587. imeth    gTLineDirective()
  588. {
  589.     if (iStream  &&  LineDirectives)  {
  590.         iRLine += 2;
  591.         iOLine = -20L;
  592.         vPrintf(iStream, "\n#line %ld \"%s\"\n", iRLine, gStringValue(iTFile));
  593.     }
  594.     return self;
  595. }
  596.  
  597. imeth    gSLineDirective()
  598. {
  599.     if (iStream) {
  600.         if (LineDirectives  &&  iILine)  {
  601.             vPrintf(iStream, "\n#line %ld \"%s\"\n", iILine, gStringValue(iSFile));
  602.             iRLine += 2;
  603.             iOLine = iILine;
  604.         } else {
  605.             gPuts(iStream, "\n");
  606.             iRLine++;
  607.             iOLine = iILine ? iILine : -20L;
  608.         }
  609.     }
  610.     return self;
  611. }
  612.  
  613. imeth    gForceLineDirective()
  614. {
  615.     iOLine = -20L;
  616.     return self;
  617. }
  618.  
  619.  
  620. /*
  621.  *
  622.  *    Copyright (c) 1994-1996 Algorithms Corporation
  623.  *    3020 Liberty Hills Drive
  624.  *    Franklin, TN  37067
  625.  *
  626.  *    ALL RIGHTS RESERVED.
  627.  *
  628.  *
  629.  *
  630.  */
  631.  
  632.